package com.tsy.server.component.mybatis;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * 公共字段自动填充处理器。
 */
@Slf4j
@Component
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {

    /**
     * 插入时自动填充
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        fillTimeField(metaObject, "createTime", true);
        fillTimeField(metaObject, "updateTime", true);
    }

    /**
     * 更新时自动填充
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        fillTimeField(metaObject, "updateTime", false);
    }

    /**
     * 根据字段类型填充对应时间值（支持父类字段，兼容低版本）
     * @param metaObject 元对象
     * @param fieldName 字段名
     * @param isInsert 是否为插入操作
     */
    private void fillTimeField(MetaObject metaObject, String fieldName, boolean isInsert) {
        try {
            // 获取实体类对象及类型
            Object originalObject = metaObject.getOriginalObject();
            Class<?> entityClass = originalObject.getClass();

            // 递归查找字段（包括父类）
            Field field = findField(entityClass, fieldName);

            if (field != null) {
                field.setAccessible(true);
                Class<?> fieldType = field.getType();

                // 判断字段类型并填充对应值
                if (fieldType == Long.class || fieldType == long.class) {
                    long timestamp = LocalDateTime.now()
                            .atZone(ZoneId.systemDefault())
                            .toInstant()
                            .toEpochMilli();
                    // 根据操作类型选择填充方法
                    if (isInsert) {
                        this.strictInsertFill(metaObject, fieldName, Long.class, timestamp);
                    } else {
                        this.strictUpdateFill(metaObject, fieldName, Long.class, timestamp);
                    }
                } else if (fieldType == LocalDateTime.class) {
                    LocalDateTime now = LocalDateTime.now();
                    if (isInsert) {
                        this.strictInsertFill(metaObject, fieldName, LocalDateTime.class, now);
                    } else {
                        this.strictUpdateFill(metaObject, fieldName, LocalDateTime.class, now);
                    }
                }
            }
        } catch (Exception e) {
            // 字段不存在或反射异常时不做处理
             log.warn("自动填充字段 {} 失败: {}", fieldName, e.getMessage());
        }
    }

    /**
     * 递归查找类及其父类中的字段
     * @param clazz 当前类
     * @param fieldName 字段名
     * @return 找到的字段，未找到返回null
     */
    private Field findField(Class<?> clazz, String fieldName) {
        // 递归终止条件：已经查找到Object类仍未找到
        if (clazz == Object.class || clazz == null) {
            return null;
        }

        try {
            // 在当前类中查找字段
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            // 当前类未找到，递归查找父类
            return findField(clazz.getSuperclass(), fieldName);
        }
    }
}
